package com.aivin.h16_lib;


import com.aivin.h16_lib.udp.OnReceiveUdpDataCallback;
import com.walkera.wktools.tools.WkByteBitTools;
import com.walkera.wktools.tools.WkLogTool;

import java.io.IOException;
import java.net.*;

/**
 * 客户端先给服务端发送消息。
 * 然后服务器获得发送方的ip，
 * 然后往约定的端口发送。
     UdpClientNormal udpClient = UdpClientNormal.getIntance()
     .initServer("192.168.1.21" , 8810)
     .setDataListener(new OnReceiveUdpDataCallback() {
      @Override
    public void onReceiveUdpData(byte[] data) {
      getFcDataFrame(data); // udp
    }
    }) ;
     wkHeartBeatTool.startDelayedAction(udpClient,500);
 */
public class UdpClientNormal implements Runnable{
    private  String ip = "0.0.0.0";
    private  int port = 0;
    private boolean isRunning = false;
    private DatagramSocket socketSender =null ;
    private DatagramSocket socketReceive =null;
    private int localPortSend = 45673 ;
    private int localPortReceive = 45674 ;
    private final byte [] receiveBuffer =new byte[1024];
    private OnReceiveUdpDataCallback onReceiveUdpDataCallback;

    private UdpClientNormal(){
        reConnect(false);
    }
    public synchronized static UdpClientNormal getIntance(){
        return SingletonFactory.instance;
    }

    private static class SingletonFactory  {
        private static final UdpClientNormal instance = new UdpClientNormal();
    }


    @Override
    public void run() {
        DatagramPacket packet = new DatagramPacket(receiveBuffer, receiveBuffer.length);

        while (isRunning){
            if(socketReceive.isClosed()){
                WkLogTool.showLog("DatagramSocket udp 通道关闭 ，退出循环" );
                break;
            }

            try {
                // 阻塞 ，调用 close() 后，此处会报错 java.net.SocketException: socket closed
                socketReceive.receive(packet);
            } catch (Exception e) {
                WkLogTool.showLog("udp 接收出现异常 ，"+ e.getMessage());
            }
            byte[] dataRev= WkByteBitTools.subBytes(packet.getData(),packet.getOffset(),packet.getLength());
            if(onReceiveUdpDataCallback!=null){
                onReceiveUdpDataCallback.onReceiveUdpData(dataRev);
            }

            try {
                Thread.sleep(30);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        WkLogTool.showLog("退出循环");

    }

    public void reConnect(boolean isReconnect){
        if(isReconnect){
            WkLogTool.showLog("本次是重连");
        }
        try {
            socketSender = new DatagramSocket(null);
            socketSender.bind( new InetSocketAddress( localPortSend));

            WkLogTool.showLog("发送端 DatagramSocket 创建成功 ,本地端口："+socketSender.getLocalPort());
            socketReceive = new DatagramSocket(localPortReceive);
            isRunning = true ;
        } catch ( Exception e) {
            e.printStackTrace();
        }
    }

    public UdpClientNormal initServer(String serverHost , int serverPort){
        this.ip=serverHost ;
        this.port=serverPort ;
        return this ;
    }



    public UdpClientNormal setDataListener(OnReceiveUdpDataCallback  callback){
        this.onReceiveUdpDataCallback =callback  ;
        return this;
    }

    public void sendData  (byte [] cmds)   {
        if(socketSender==null){
            WkLogTool.showLog("socketSender==null ,发生异常");
            return;
        }

        if(cmds==null || cmds.length==0){
            return;
        }

        try {
            DatagramPacket packet = new DatagramPacket(cmds, cmds.length, InetAddress.getByName(ip), port);
            socketSender.send(packet);
        } catch (IOException e) {
            e.printStackTrace();
            WkLogTool.showLog("udp发送异常="+ e.getMessage());
        }

        WkLogTool.showLog("发送数据："+ WkByteBitTools.byte2HexStr(cmds));
    }


    public void exitUdpServe(){
        if(socketSender!=null){
            if (!socketSender.isClosed()){
                socketSender.close();
            }
            socketSender.disconnect();
            socketSender = null;
            System.out.println("发送 DatagramSocket 已经关闭");
        }

        if(socketReceive!=null){
            if (!socketReceive.isClosed()){
                socketReceive.close();
            }
            socketReceive.disconnect();
            socketReceive = null;
            System.out.println("接收 DatagramSocket 已经关闭");
        }

        isRunning = false ;
        WkLogTool.showLog("关闭udp done!");
    }
}